package com.cocotingo.snail.template.parser;

import java.awt.Color;
import java.awt.Font;
import java.util.HashSet;
import java.util.Set;

import com.cocotingo.snail.Image;
import com.cocotingo.snail.PaintMode;
import com.cocotingo.snail.ResizableImage;
import com.cocotingo.snail.template.TemplateLoader;
import com.cocotingo.snail.template.TemplateParserException;
import com.cocotingo.snail.template.TemplateRuntimeException;
import com.cocotingo.snail.util.Alignment;

public final class AttributeParsers {
	
	public static Set<AttributeParser> getDefaultParsers() {
		HashSet<AttributeParser> parsers = new HashSet<AttributeParser>();
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return int.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				try {
					return Integer.parseInt(string);
				} catch (NumberFormatException e) {
					throw new TemplateRuntimeException("incorrect integer format: " + string, e);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return float.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				try {
					return Float.parseFloat(string);
				} catch (NumberFormatException e) {
					throw new TemplateRuntimeException("incorrect float format: " + string, e);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return double.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				try {
					return Double.parseDouble(string);
				} catch (NumberFormatException e) {
					throw new TemplateRuntimeException("incorrect double format: " + string, e);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return boolean.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("true")) {
					return Boolean.TRUE;
				} else if (string.equals("false")) {
					return Boolean.FALSE;
				} else {
					throw new TemplateRuntimeException("invalid boolean value: " + string);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return String.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				return string;
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return PaintMode.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("disabled")) {
					return PaintMode.DISABLED;
				} else if (string.equals("buffered")) {
					return PaintMode.BUFFERED;
				} else if (string.equals("directly")) {
					return PaintMode.DIRECTLY;
				} else {
					throw new TemplateRuntimeException("invalid PaintMode value: " + string);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return Image.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("null")) {
					return null;
				} else {
					try {
						Image value = loader.getResourceAsImage(string);
						if (value == null) throw new TemplateRuntimeException("can not find resource:" + string);
						return value;
					} catch (ClassCastException e) {
						throw new TemplateRuntimeException("incorrect resource type: " + string);
					}
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return ResizableImage.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("null")) {
					return null;
				} else {
					try {
						ResizableImage value = loader.getResourceAsResizableImage(string);
						if (value == null) throw new TemplateRuntimeException("can not find resource:" + string);
						return value;
					} catch (ClassCastException e) {
						throw new TemplateRuntimeException("incorrect resource type: " + string);
					}
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return Font.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("null")) {
					return null;
				} else {
					try {
						Font value = loader.getResourceAsFont(string);
						if (value == null) throw new TemplateRuntimeException("can not find resource:" + string);
						return value;
					} catch (ClassCastException e) {
						throw new TemplateRuntimeException("incorrect resource type: " + string);
					}
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return Color.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("null")) {
					return null;
				} else {
					try {
						int rgb = ParserUtility.getColorValueFromString(string);
						return new Color(rgb);
					} catch (TemplateParserException e1) {
						try {
							Color value = loader.getResourceAsColor(string);
							if (value == null) throw new TemplateRuntimeException("incorrect color format or can not find color resource:" + string);
							return value;
						} catch (ClassCastException e) {
							throw new TemplateRuntimeException("incorrect resource type: " + string);
						}
					}
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return Alignment.Horizontal.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("left")) {
					return Alignment.Horizontal.LEFT;
				} else if (string.equals("center")) {
					return Alignment.Horizontal.CENTER;
				} else if (string.equals("right")) {
					return Alignment.Horizontal.RIGHT;
				} else {
					throw new TemplateRuntimeException("invalid Alignment value: " + string);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return Alignment.Vertical.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("top")) {
					return Alignment.Vertical.TOP;
				} else if (string.equals("center")) {
					return Alignment.Vertical.CENTER;
				} else if (string.equals("bottom")) {
					return Alignment.Vertical.BOTTOM;
				} else {
					throw new TemplateRuntimeException("invalid Alignment value: " + string);
				}
			}
		});
		parsers.add(new AttributeParser() {
			@Override
			public Class<?> getResultType() {
				return Alignment.class;
			}
			@Override
			public Object parse(TemplateLoader loader, String string) throws TemplateRuntimeException {
				if (string.equals("left&top")) {
					return Alignment.LEFT_TOP;
				} else if (string.equals("left&center")) {
					return Alignment.LEFT_CENTER;
				} else if (string.equals("left&bottom")) {
					return Alignment.LEFT_BOTTOM;
				} else if (string.equals("center&top")) {
					return Alignment.CENTER_TOP;
				} else if (string.equals("center&center")) {
					return Alignment.CENTER_CENTER;
				} else if (string.equals("center&bottom")) {
					return Alignment.CENTER_BOTTOM;
				} else if (string.equals("right&top")) {
					return Alignment.RIGHT_TOP;
				} else if (string.equals("right&center")) {
					return Alignment.RIGHT_CENTER;
				} else if (string.equals("right&bottom")) {
					return Alignment.RIGHT_BUTTOM;
				} else {
					throw new TemplateRuntimeException("invalid Alignment value: " + string);
				}
			}
		});
		return parsers;
	}

	private AttributeParsers() {
	}
	
}
